#include "h_cc2640r2f_uart.h"


#include <ti/drivers/uart/UARTCC26XX.h>
#include <stdio.h>
#include <stdarg.h>

////////////////////////////////////////////////////////////////////////////////
/*
    User define part
*/
#define H_CC2640R2F_UARTBaudRate                      H_CC2640R2F_UART_BaudRate

//#define  H_CC2640R2F_UART_RxLength                     H_CC2640R2F_UART_RxLength
unsigned char H_CC2640R2F_UARTRxBuffer[H_CC2640R2F_UART_RxLength];
volatile unsigned short H_CC2640R2F_UARTRxLength = 0U;
////////////////////////////////////////////////////////////////////////////////
static UART_Handle H_CC2640R2F_UARTHandle = NULL;

static unsigned char H_CC2640R2F_UARTTxState = 0U;

//volatile unsigned char H_CC2640R2F_UARTRxEnable = 0U;

#if (H_CC2640R2F_UART_TskMd_Enable)
#include <string.h>

#include <ti/sysbios/knl/Task.h>
//#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
//#include <ti/sysbios/knl/Queue.h>

#include <ti/sysbios/BIOS.h>

static Event_Handle H_CC2640R2F_UARTEventHandle = NULL;
static Event_Struct H_CC2640R2F_UARTEventStruct;

#define H_CC2640R2F_UARTTxLength                       H_CC2640R2F_UART_TxLength

//#if (H_CC2640R2F_UARTTxLength > 255)
unsigned short H_CC2640R2F_UARTTxBufferLength = 0;
//#else
//unsigned char H_CC2640R2F_UARTTxBufferLength = 0;
//#endif

unsigned char H_CC2640R2F_UARTTxBuffer[H_CC2640R2F_UARTTxLength];
#endif

/*
    A send buff by UART function, use the TI official library function.
*/
/*
static void h_cc2640r2f_uart_txbuffer(const unsigned char *buff, unsigned short length)//size_t length)
{
    UART_write(H_CC2640R2F_UARTHandle, buff, length);
}
*/

/*
    This is just a test/debug function, in real project should be deleted.
*/
void H_CC2640R2F_UART_TxBuff(const unsigned char *buff, unsigned short len)
{
#if (H_CC2640R2F_UART_TskMd_Enable)
    H_CC2640R2F_UARTTxBufferLength = len;
    memcpy(H_CC2640R2F_UARTTxBuffer, buff, len);
    Event_post(H_CC2640R2F_UARTEventHandle, H_CC2640R2F_UARTEvent_TX);
#else
    if(UART_STATUS_SUCCESS == UART_write(H_CC2640R2F_UARTHandle, buff, len))
    {
        H_CC2640R2F_UARTTxState = 0U;
    }
    else
    {
        H_CC2640R2F_UARTTxState = 1U;
    }
#endif
}

/*
    System debug output function, just like printf()
*/
void H_CC2640R2F_UART_printf(const char* format, ...)
{
    va_list arg;
    va_start(arg, format);
    unsigned char buf[H_CC2640R2F_UART_RxLength];
    unsigned short len;
    len = vsprintf((char*)buf, format, arg);
    H_CC2640R2F_UART_TxBuff(buf, len);
}

void H_CC2640R2F_UART_RxEnable(void)
{
    UART_read(H_CC2640R2F_UARTHandle, H_CC2640R2F_UARTRxBuffer, \
            H_CC2640R2F_UART_RxLength);
}
/*
    CC2640R2F UART Receive Callback function
*/
static void H_CC2640R2F_UART_RxCallback(UART_Handle handle, void *buf, size_t count)
{
    //H_CC2640R2F_UART_TxBuff(buf, count);
    //UART_read(handle, H_CC2640R2F_UARTRxBuffer, \
                H_CC2640R2F_UART_RxLength);
                
    //H_CC2640R2F_UART_printf("Get the data length is %d\r\n", count);
    
    

    //UART_read(handle, H_CC2640R2F_UARTRxBuffer, \
            H_CC2640R2F_UART_RxLength);

    //H_CC2640R2F_UART_RxEnable();
    
    H_CC2640R2F_UARTRxLength = count;
}

/*
    CC2640R2F UART Send Callback function
*/
static void H_CC2640R2F_UART_TxCallback(UART_Handle handle, void *buf, size_t count)
{
    //UART_write(handle, buf, count);
  if(1U == H_CC2640R2F_UARTTxState)
  {
    if(UART_STATUS_SUCCESS == UART_write(handle, buf, count))
    {
        H_CC2640R2F_UARTTxState = 0U;
    }
    else
    {
        H_CC2640R2F_UARTTxState = 1U;
    }
  }
}

/*
    Init the UART of CC2640R2F
*/
signed char H_CC2640R2F_UART_Init(void)
{
    UART_Params h_cc2640r2f_uartparams;
    
    UART_init();
    UART_Params_init(&h_cc2640r2f_uartparams);
    
    h_cc2640r2f_uartparams.readMode = UART_MODE_CALLBACK; 
    h_cc2640r2f_uartparams.writeMode = UART_MODE_BLOCKING;//UART_MODE_CALLBACK;//UART_MODE_BLOCKING;//;
    //h_cc2640r2f_uartparams.readTimeout = 65535U;
    //h_cc2640r2f_uartparams.writeTimeout = 0U;//65535U;
    h_cc2640r2f_uartparams.readCallback = H_CC2640R2F_UART_RxCallback;
    h_cc2640r2f_uartparams.writeCallback = H_CC2640R2F_UART_TxCallback;
    h_cc2640r2f_uartparams.readReturnMode = UART_RETURN_NEWLINE;//UART_RETURN_FULL;
    h_cc2640r2f_uartparams.readDataMode = UART_DATA_BINARY;
    h_cc2640r2f_uartparams.writeDataMode = UART_DATA_BINARY;//UART_DATA_TEXT;
    h_cc2640r2f_uartparams.readEcho = UART_ECHO_OFF;
    h_cc2640r2f_uartparams.baudRate = H_CC2640R2F_UARTBaudRate;
    h_cc2640r2f_uartparams.dataLength = UART_LEN_8;
    h_cc2640r2f_uartparams.stopBits = UART_STOP_TWO;//UART_STOP_ONE;
    h_cc2640r2f_uartparams.parityType = UART_PAR_EVEN;//UART_PAR_NONE;
    
    H_CC2640R2F_UARTHandle = UART_open(0, &h_cc2640r2f_uartparams);
    UART_control(H_CC2640R2F_UARTHandle, UARTCC26XX_RETURN_PARTIAL_ENABLE, NULL);
    //UART_read(H_CC2640R2F_UARTHandle, H_CC2640R2F_UARTRxBuffer, \
                H_CC2640R2F_UART_RxLength);
    
    
    return 0;
}

#if (H_CC2640R2F_UART_TskMd_Enable)

// Task configuration
Task_Struct uartTaskMd_Task;

#if defined __TI_COMPILER_VERSION__
#pragma DATA_ALIGN(uartTaskMd_Task_Stack, 8)
#else
#pragma data_alignment=8
#endif
unsigned char uartTaskMd_Task_Stack[H_CC2640R2F_UART_TskMd_Task_Stack_Size];


static void h_cc2640r2f_uart_taskmode_taskFxn(UArg a0, UArg a1)
{
    //Registe the uart event
    Event_Params evParams;
    Event_Params_init(&evParams);
    Event_construct(&H_CC2640R2F_UARTEventStruct, &evParams);
    H_CC2640R2F_UARTEventHandle = \
                    Event_handle(&H_CC2640R2F_UARTEventStruct);
  
    //The uart  peripheral initialize
    H_CC2640R2F_UART_Init();
    
    for(;;)
    {
        unsigned int events;
        
        events = Event_pend(H_CC2640R2F_UARTEventHandle, \
                                Event_Id_NONE, \
                                  H_CC2640R2F_UARTEvent_ALL, \
                                    BIOS_WAIT_FOREVER);
        
        if(events & H_CC2640R2F_UARTEvent_RX)
        {
            UART_read(H_CC2640R2F_UARTHandle, H_CC2640R2F_UARTRxBuffer, \
                H_CC2640R2F_UART_RxLength);
        }
        if(events & H_CC2640R2F_UARTEvent_TX)
        {
            //UART_write(H_CC2640R2F_UARTHandle, H_CC2640R2F_UARTTxBuffer, \
                       H_CC2640R2F_UARTTxBufferLength);
            if(UART_ERROR == UART_write(H_CC2640R2F_UARTHandle, H_CC2640R2F_UARTTxBuffer, H_CC2640R2F_UARTTxBufferLength))
            {
                H_CC2640R2F_UARTTxState = 1U;
            }
        }
    }
}
/*
    This is a function for UART task mode task creating
*/
void H_CC2640R2F_UART_TaskMode_createTask(void)
{
    Task_Params taskParams;

    // Configure task
    Task_Params_init(&taskParams);
    taskParams.stack = uartTaskMd_Task_Stack;
    taskParams.stackSize = H_CC2640R2F_UART_TskMd_Task_Stack_Size;
    taskParams.priority = H_CC2640R2F_UART_TskMd_Priority;
    Task_construct(&uartTaskMd_Task, \
                    h_cc2640r2f_uart_taskmode_taskFxn, &taskParams, NULL);
}

#endif
